package com.fare.taluo.core.domain.crawl.adapter.sub;

import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Source;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.util.EntityUtils;

import com.fare.taluo.core.domain.crawl.CrawlTaskModel;
import com.fare.taluo.core.domain.crawl.PageErrorResultException;
import com.fare.taluo.core.domain.crawl.adapter.AbstractAdapter;
import com.fare.taluo.core.domain.crawl.adapter.CrawlAdapterFactory;
import com.fare.taluo.core.domain.entity.crawl.FreightPriceEntity;
import com.fare.taluo.util.RegHtmlUtil;
import com.fare.taluo.util.value.NumberUtils;


public class ShenzhengAirHttpClientAdapter extends AbstractAdapter {

	private HttpClient client = null;
	
	public ShenzhengAirHttpClientAdapter(CrawlTaskModel taskModel) {
		super(taskModel);
	}

	private String fromCity(){
		return String.format("%s;%s-%s", taskModel.getFromCity(), taskModel.getFromCity().substring(0, 1),
				taskModel.getFromCityName());
	}

	private String toCity(){
		return String.format("%s;%s-%s", taskModel.getToCity(), taskModel.getToCity().substring(0, 1),
				taskModel.getToCityName());
	}

//	@Override
//	public String getUrl() {
//		operate	flightSearch
//		originalPage	index
//		hcType	DC
//		orgCity10	SZX;S-深圳
//		orgDate10	2013-4-20
//		orgDate20	2013-04-13
//		dstCity10	HRB;H-哈尔滨
//		sortType	
//		strIdentity	1365736053486fmluklennkfqqhdskwl
//		return String.format("http://www.shenzhenair.com/ticketBookingFlow/flightSearchAct.do?" +
//				"operate=flightSearch&originalPage=index&hcType=DC&orgCity10=%s&orgDate10=%s&orgDate20=%s&dstCity10=%s&sortType=&strIdentity=1365736053486fmluklennkfqqhdskwl",
//				taskModel.getFromCity(), taskModel.getSingleGrabDate(), taskModel.getSingleGrabDate(), taskModel.getToCity());
//	}
	private URI produceUri1() throws URISyntaxException {
		// 请求参数
		return new URIBuilder().addParameter("operate", "goLoadingPage")
					.addParameter("originalPage", "index")
					.addParameter("parmHide", "0")
					.addParameter("couponGiveRule", "")
					.addParameter("username", "邮箱/手机号")
					.addParameter("password", "")
					.addParameter("verifyCode", "请点击")
					.addParameter("flightConditionEntity.hcType", "DC")
					.addParameter("fromCity", taskModel.getFromCityName())
					.addParameter("flightConditionEntity.orgCity1", fromCity())
					.addParameter("toCity", taskModel.getToCityName())
					.addParameter("flightConditionEntity.dstCity0", toCity())
					.addParameter("flightConditionEntity.orgDate1", taskModel.getFlightDate())
					.addParameter("flightConditionEntity.orgDate2", taskModel.getFlightDate())
					.addParameter("orgCity10", fromCity())
					.addParameter("orgDate10", taskModel.getFlightDate())
					.addParameter("dstCity0", toCity())
					.addParameter("flightConditionEntity.hcType", "DC")
					.addParameter("orgCity10qunar", fromCity())
					.addParameter("orgDate10qunar", taskModel.getFlightDate())
					.addParameter("dstCity0qunar", toCity())
					.addParameter("selectSegment","")
					.setScheme("http")
					.setHost("www.shenzhenair.com")
					.setPath("/ticketBookingFlow/flightSearchAct.do")
					.build();
	}

	private URI produceUri2() throws URISyntaxException {
		// 请求参数
		return new URIBuilder().addParameter("operate", "flightSearch")
					.addParameter("originalPage", "index")
					.addParameter("hcType", "DC")
					.addParameter("orgCity10", fromCity())
					.addParameter("orgDate10", taskModel.getFlightDate())
					.addParameter("orgDate20", taskModel.getFlightDate())
					.addParameter("dstCity10", toCity())
					.addParameter("sortType", "")
					.addParameter("strIdentity", strIdentity)
					.setScheme("http")
					.setHost("www.shenzhenair.com")
					.setPath("/ticketBookingFlow/flightSearchAct.do")
					.build();
	}

	private String strIdentity;
	
	private String cookieStr;
	
	private String fetchURI(URI uri) throws Exception{
		HttpPost request = null;
		HttpResponse response = null;
		HttpEntity entity = null;
		 InputStream gis = null;
		InputStream is = null;
		byte data[] = null;
		try {
			if(client == null) client = super.getHttpClient();
			request = new HttpPost(uri);
			//request.setHeader("(Request-Line)", getRequestLine());
			request.setHeader("Accept", "text/html, application/xhtml+xml, */*");
			request.setHeader("Accept-Encoding", "gzip, deflate");
			request.setHeader("Accept-Language", "zh-CN");
			request.setHeader("Connection", "keep-Alive");
			request.setHeader("Cache-Control", "no-cache");
			request.setHeader("Content-Type", "application/x-www-form-urlencoded");
			if(StringUtils.isNotBlank(cookieStr)) 
				request.setHeader("Cookie", cookieStr);
			request.setHeader("Host", "www.shenzhenair.com");
			request.setHeader("User-Agent","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0");
			request.setHeader("Referer","http://www.shenzhenair.com/ticketBookingFlow/flightSearchAct.do");
			response = client.execute(request);
			entity = response.getEntity();
			if (entity != null) {
				is = entity.getContent();
				Header encoding = entity.getContentEncoding();
				if (encoding != null && encoding.getValue().equals("gzip")) {
					data = super.writeByte(new GZIPInputStream(is));
				}else{
					data = super.writeByte(is);
				}
			}
			
			return new String(data,"GBK");
		} finally {
			if(request != null) request.releaseConnection();
			request = null;
			if(entity != null) EntityUtils.consume(entity);
			entity = null;
			response = null;
			data = null;
				 if(gis != null) 
					 try{gis.close();}catch(Exception e){}
				  gis = null;
			
		}
	}
	//设置深圳查询时一个订单的标识符
	private void setRequestParamValues(String page){
		String identityInput = RegHtmlUtil.regStr(page, "<input type=\"hidden\" name=\"strIdentity\" value=\"\\w{30,40}\"/>",0);
		strIdentity = identityInput.substring(identityInput.indexOf("value=")+7, identityInput.indexOf("/>")-1);
		AbstractHttpClient aclient = (AbstractHttpClient)client;
		List<Cookie> cookies = aclient.getCookieStore().getCookies();
		StringBuilder sbuilder = new StringBuilder();
		for(Cookie c : cookies){
			sbuilder.append(c.getName()).append("=").append(c.getValue()).append(";");
		}
		cookieStr = sbuilder.toString();
	}

	public Object fetch(String url) throws Exception {
		try{
			String page1 = this.fetchURI(produceUri1());
			this.setRequestParamValues(page1);
			return this.fetchURI(produceUri2());
		}finally{
			cookieStr = null;
			strIdentity = null;
			client = null;
		}
	}
	public  List<Object> paraseToVo(Object fetchObject) throws Exception {
		List<Object> result=new ArrayList<Object>();
		String page = (String)fetchObject;
		Source source = new Source(page);
		
		net.htmlparser.jericho.Element table = null;
		net.htmlparser.jericho.Element tbody = null;
		List<net.htmlparser.jericho.Element> trs = null;
		List<net.htmlparser.jericho.Element> tds = null;
		try{
			for(int i = 1 ;i < 100 ; i++){ //一般不会超过这个数，每一个flightTable是一个航班
				table = source.getElementById("flightTable"+i);//获得航班的表格
				if(table != null){
					try{
						tbody = this.getChildElement(table, HTMLElementName.TBODY);
						if(tbody != null) {
							trs = tbody.getChildElements();
						}else{
							trs = table.getChildElements();
						}
						if(trs != null && !trs.isEmpty()){ //每一行是一个航班记录信息
							for(Element tr : trs){
								tds = tr.getChildElements(); //各个单元格中存储了不同的数据（航班号，起始时间等）
								result.add(this.compPlaneInfo(tds));
							}
						}
					}catch(Exception e){
						if(logger.isDebugEnabled()){
							e.printStackTrace();
						}
						logger.error(e);
					}finally{
						table = null;
						trs = null;
						tds = null;
					}
				}
			}
		}finally{
			source = null;
		}
	    return result;
	}
	private Element getChildElement(Element e ,String tagName){
		Element ele = null;
		if(e != null){
			for(Element l : e.getChildElements()){
				if(tagName.equalsIgnoreCase(l.getName())){
					return l;
				}
			}
		}
		return ele;
	}
	
	private FreightPriceEntity compPlaneInfo(List<Element> tds){
		String lowerprice = null;
		String highprice = null;
		String flightNo = null;
		String flightType = null;
		String depTime = null;
		String arrTime = null;
		List<Double> values = null;
		if(tds != null && !tds.isEmpty()){
			//第一个单元格第一个strong标签的内容
			flightNo = tds.get(0).getFirstElement(HTMLElementName.STRONG).getTextExtractor().toString();
			//第二个单元第一个strong标签的内容
			depTime = tds.get(1).getFirstElement(HTMLElementName.STRONG).getTextExtractor().toString(); 
			//第二个单元第二个DIV标签的内容
			arrTime = tds.get(1).getAllElements(HTMLElementName.DIV).get(1).getTextExtractor().toString(); 
			//第三个单元格，截取内容
			flightType = RegHtmlUtil.regStr(tds.get(2).getTextExtractor().toString(),"机型:(.+)经停:",1); 
			//获得所有各种价格，第三个单元格之后都是价格
			values = this.getAllPrices(tds.subList(3, tds.size()));
			lowerprice = String.valueOf(NumberUtils.getMinValue(values)); 
			highprice = String.valueOf(NumberUtils.getMaxValue(values));
		}
		return CrawlAdapterFactory.createPlaneInfo(taskModel, "ZH", "深航", "深圳航空公司", 
				depTime, arrTime, flightNo,
				lowerprice, null, 
				highprice, flightType);
	}
	
	private List<Double> getAllPrices(List<Element> tds){
		List<Double> prices = new ArrayList<Double>();
		String p = null;
		if(tds != null && !tds.isEmpty()){
			for(Element e : tds){
				p = RegHtmlUtil.regStr(e.toString(), "<div.*>\\s*￥(\\d+)\\s*</div>", 1);
				if(StringUtils.isNotBlank(p)){
					prices.add(Double.parseDouble(p.trim()));
				}
			}
		}
		return prices;
	}

	@Override
	public String getUrl() {
		return "http://www.shenzhenair.com/servlet/SearchEngineServlet?pc="+
				taskModel.getFromCity()+"&pd="+taskModel.getToCity()+"&pe="+taskModel.getFlightDate();
	}

	@Override
	public boolean validateFetch(Object fetchObject) throws Exception {
		if(fetchObject == null){
			return false;
		}else if(fetchObject instanceof String){
			if(((String)fetchObject).length() < 2000){
				throw new PageErrorResultException("抓取的数据不正确(长度少于2000)");
			}
			//验证字符串里是否包含抓取的错误信息
			String result = RegHtmlUtil.regStr((String)fetchObject, this.getErrors());
			if(result != null){
				throw new PageErrorResultException(result);
			}
		}
		return true;
	}	
	
	private List<String> getErrors(){
		List<String> errors = new ArrayList<String>();
		errors.add("404 Not Found");
		errors.add("<img src=\"/images/load_pic2.jpg\" alt=\"航班信息查询中，请稍候……\"");
		errors.add("Welcome To Zscaler Directory Authentication");
		return errors;
	}

//	public static void  main(String[] arg) throws Exception{
//		CrawlContext.getInstance().setDebug(true);
//		
//		try{
////			taskModelEntity taskModel = new taskModelEntity();
////			taskModel.setGrabChannelId(ShenzhengAirHtmlUtilAdapter.ShenZheng_GradChannel);
////			taskModel.setIsReturn(0);
////			taskModel.setFromCity("CAN");
////			taskModel.setFromCityName("广州");
////			taskModel.setToCity("PVG");
////			taskModel.setToCityName("上海浦东");
////			taskModel.setSingleGrabDate("2013-04-27");
////
////			//logger.info("抓取引警系统配置文件统一注册......");
////			ConfigLoader.initLoader();
////
////			System.out.println("fetch......");
////			ShenzhengAirHttpClientAdapter c = new ShenzhengAirHttpClientAdapter(taskModel);
////			Object obj = c.fetch(null);
////			
////			FileUtils.write(new File("F:/temp/hbase/sz.htm"), obj.toString());
////			
////			//Object obj = FileUtils.readFileToString(new File("F:/temp/hbase/source-1.txt"));
////			//System.out.println(obj.toString());
////			List<Object> results = c.paraseToVo(obj);
////			System.out.println("println......");
////			for (Object o : results) {
////				PlaneInfoEntity p = (PlaneInfoEntity)o;
////				System.out.println(p.toString());
////			}
//		}catch(Exception e){
//			e.printStackTrace();
//		}finally{
//			System.out.println("finish ok....");
//			Runtime.getRuntime().exit(1);
//		}
//		
//	}  
}
